package cn.elane.elastic.global.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Chenyu
 * @date 2020-3-23
 */
public class Converter {

	private static Logger logger = LoggerFactory.getLogger(Converter.class.getName());

	/**
	 * 将Object转字符串.如果为Date/java.sql.Date类型将对其进行格式转换[yyyy-MM-dd HH:mm:ss,yyyy-MM-dd],如果失败,直接toString.
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static String toString(Object obj, String defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		Class<?> clazz = obj.getClass();
		if (clazz == Date.class || clazz == java.sql.Date.class) {
			try {
				return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(obj);
			} catch (Exception e) {
				try {
					return new SimpleDateFormat("yyyy-MM-dd").format(obj);
				} catch (Exception e1) {
					return obj.toString();
				}
			}
		}
		return obj.toString();
	}

	/**
	 * Integer转换.
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r r
	 */
	public static Integer toInteger(Object obj, Integer defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		try {
			return Integer.valueOf(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * Boolean类型转换.
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Boolean toBoolean(Object obj, Boolean defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		try {
			return Boolean.valueOf(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * Long类型转换.
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Long toLong(Object obj, Long defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		try {
			return Long.valueOf(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * Double转换
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Double toDouble(Object obj, Double defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		try {
			return Double.valueOf(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * BigDecimal转换.
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static BigDecimal toBigDecimal(Object obj, BigDecimal defaultValue) {
		if (obj == null) {
			return defaultValue;
		}
		try {
			if (obj instanceof Integer) {
				return new BigDecimal(toInteger(obj));
			} else if (obj instanceof Long) {
				return new BigDecimal(toLong(obj));
			} else if (obj instanceof BigInteger) {
				return new BigDecimal((BigInteger) obj);
			} else if (obj instanceof Double) {
				return BigDecimal.valueOf(toDouble(obj));
			} else if (obj instanceof BigDecimal) {
				return new BigDecimal(obj.toString());
			} else {
				return defaultValue;
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * String转换,默认值:""
	 *
	 * @param obj p
	 * @return r
	 */
	public static String toString(Object obj) {
		return toString(obj, "");
	}

	/**
	 * Integer转换,默认值:0
	 *
	 * @param obj p
	 * @return r
	 */
	public static Integer toInteger(Object obj) {
		return toInteger(obj, 0);
	}

	/**
	 * Boolean转换,默认:false
	 *
	 * @param obj p
	 * @return r
	 */
	public static Boolean toBoolean(Object obj) {
		return toBoolean(obj, false);
	}

	/**
	 * Long转换,默认:0
	 *
	 * @param obj p
	 * @return r
	 */
	public static Long toLong(Object obj) {
		return toLong(obj, 0L);
	}

	/**
	 * Double转换,默认:0.0D
	 *
	 * @param obj p
	 * @return r
	 */
	public static Double toDouble(Object obj) {
		return toDouble(obj, 0D);
	}

	/**
	 * 驼峰命名转换:user_id转为userId
	 *
	 * @param dbName p
	 * @return r
	 */
	public static String toJavaName(String dbName) {
		String[] ss = dbName.split("_");
		StringBuffer sb = new StringBuffer();
		for (String s : ss) {
			sb.append(toFirstUppercase(s.toLowerCase()));
		}
		return toFirstLowercase(sb.toString());
	}

	/**
	 * 首字母大写转换:test转为Test
	 *
	 * @param str p
	 * @return r
	 */
	public static String toFirstUppercase(String str) {
		if (str == null || "".equals(str)) {
			return str;
		}
		return str.substring(0, 1).toUpperCase() + str.substring(1);
	}

	/**
	 * 首字母小写转换:TEST转为tEST
	 *
	 * @param str p
	 * @return r
	 */
	public static String toFirstLowercase(String str) {
		if (str == null || "".equals(str)) {
			return str;
		}
		return str.substring(0, 1).toLowerCase() + str.substring(1);
	}

	/**
	 * Float转换,默认:0
	 *
	 * @param obj p
	 * @return r
	 */
	public static Float toFloat(Object obj) {
		return toFloat(obj, 0F);
	}

	/**
	 * Float转换
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Float toFloat(Object obj, Float defaultValue) {
		try {
			return Float.valueOf(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * Date转换,默认:null
	 *
	 * @param obj p
	 * @return r
	 */
	public static Date toDate(Object obj) {
		return toDate(obj, null);
	}

	/**
	 * Date转换,默认:null<br>默认格式:yyyy-MM-dd
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Date toDate(Object obj, Date defaultValue) {
		try {
			return new SimpleDateFormat("yyyy-MM-dd").parse(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * Time转换,默认:null
	 *
	 * @param obj p
	 * @return r
	 */
	public static Date toTime(Object obj) {
		return toTime(obj, null);
	}

	/**
	 * Time转换<br>默认格式:HH:mm:ss
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Date toTime(Object obj, Date defaultValue) {
		try {
			return new SimpleDateFormat("HH:mm:ss").parse(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * DateTime转换,默认:null
	 *
	 * @param obj p
	 * @return r
	 */
	public static Date toDateTime(Object obj) {
		return toDateTime(obj, null);
	}

	/**
	 * DateTime转换<br>格式:yyyy-MM-dd HH:mm:ss
	 *
	 * @param obj          p
	 * @param defaultValue v
	 * @return r
	 */
	public static Date toDateTime(Object obj, Date defaultValue) {
		try {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(toString(obj));
		} catch (Exception e) {
			logger.error(e.getMessage());
			return defaultValue;
		}
	}

	/**
	 * 将数组second追加到数组first后，并返回数组first
	 *
	 * @param first  p
	 * @param second p2
	 * @return r
	 */
	public static <T> T[] concat(T[] first, T[] second) {
		T[] result = Arrays.copyOf(first, first.length + second.length);
		System.arraycopy(second, 0, result, first.length, second.length);
		return result;
	}

	/**
	 * 获取元素t在数组array中的下标，当数组无效或元素未找到时返回-1
	 *
	 * @param array p
	 * @param t     p2
	 * @return r
	 */
	public static <T> int indexOf(T[] array, T t) {
		if (array == null || array.length == 0) {
			return -1;
		}
		for (int i = 0; i < array.length; i++) {
			if (array[i].equals(t)) {
				return i;
			}
		}
		return -1;
	}

	/**
	 * 将map集合转为json格式字符串.
	 *
	 * @param map map集合.
	 * @return r json格式字符串.
	 */
	public static String map2JsonStr(Map<String, Object> map) {
		if (map != null && map.size() > 0) {
			return JSONObject.toJSONString(map);
		}
		return null;
	}

	/**
	 * 将json格式字符串转为Java的List集合
	 *
	 * @param jsonStr json格式字符串
	 * @return r List
	 */
	public static List<Object> jsonStr2List(String jsonStr) {
		if (jsonStr == null || "".equals(jsonStr)) {
			return null;
		}
		JSONArray array = JSONArray.parseArray(jsonStr);
		return array.toJavaList(Object.class);
	}

	/**
	 * 将List<String>集合转为数组
	 *
	 * @param list List集合
	 * @return r String类型数组
	 */
	public static String[] toArray(List<String> list) {
		if (list != null && list.size() > 0) {
			return list.toArray(new String[0]);
		} else {
			return null;
		}
	}

	/**
	 * 将List<String>集合转为数组
	 *
	 * @param list List集合
	 * @return r String类型数组
	 */
	public static String[] toArray(List<String> list, Class clazz) {
		if (list != null && list.size() > 0) {
			return list.toArray(new String[0]);
		} else {
			return null;
		}
	}

	/**
	 * 将String字符串转换为T类型的对象实例
	 *
	 * @param str   p
	 * @param clazz p2
	 * @return r
	 */
	@SuppressWarnings("unchecked")
	public static <T> T to(String str, Class<T> clazz) {
		if (str == null) {
			return null;
		}
		Object obj;
		if (clazz == Integer.class) {
			obj = toInteger(str);
		} else if (clazz == Float.class) {
			obj = toFloat(str);
		} else if (clazz == Date.class) {
			obj = toDateTime(str);
		} else if (clazz == Double.class) {
			obj = toDouble(str);
		} else if (clazz == Long.class) {
			obj = toLong(str);
		} else if (clazz == Boolean.class) {
			obj = toBoolean(str);
		} else if (clazz == String.class) {
			obj = toString(str);
		} else {
			logger.error("未处理的类型转换");
			throw new RuntimeException("未处理的类型转换");
		}
		return (T) obj;
	}

	/**
	 * 将String数组转换为T类型的数组
	 *
	 * @param array p
	 * @param clazz p2
	 * @return r
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] toArray(String[] array, Class<T> clazz) {
		try {
			if (array == null) {
				return null;
			}
			int len = array.length;
			Object[] objs = new Object[len];
			for (int i = 0; i < len; i++) {
				objs[i] = to(array[i], clazz);
			}
			return (T[]) objs;
		} catch (Exception e) {
			logger.error(e.getMessage());
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	 * 年月日格式 yyyy-MM-dd
	 *
	 * @param temporal p
	 * @return r
	 */
	public static String formatYYYYMMDD(TemporalAccessor temporal) {
		return format(temporal, "yyyy-MM-dd");
	}

	/**
	 * 时分秒格式化 HH:mm:ss
	 *
	 * @param localTime p
	 * @return r
	 */
	public static String formatHHmmss(LocalTime localTime) {
		return format(localTime, "HH:mm:ss");
	}

	/**
	 * 年月日时分秒格式 yyyy-MM-dd HH:mm:ss
	 *
	 * @param temporal
	 * @return
	 */
	public static String formatYMDHMS(TemporalAccessor temporal) {
		return format(temporal, "yyyy-MM-dd HH:mm:ss");
	}

	/**
	 * 字符串解析成LocalDateTime
	 *
	 * @param time    p
	 * @param pattern p2
	 * @return r
	 */
	public static LocalDateTime parseLocalDateTime(String time, String pattern) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
		return LocalDateTime.parse(time, formatter);
	}

	/**
	 * 字符串解析成LocalDate
	 *
	 * @param time
	 * @param pattern
	 * @return r
	 */
	public static LocalDate parseLocalDate(String time, String pattern) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
		return LocalDate.parse(time, formatter);
	}

	/**
	 * 字符串解析成Date
	 *
	 * @param time    格式化的时间
	 * @param pattern 匹配的格式
	 * @return r
	 */
	public static Date parse2Date(String time, String pattern) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
		return Date.from(LocalDate.parse(time, formatter).atStartOfDay(ZoneId.systemDefault()).toInstant());
	}

	/**
	 * 将数据库Timestamp转为yyyy-MM-dd HH:mm:ss字符串
	 *
	 * @param dateStr p
	 * @return r
	 */
	public static String toDateStr(Timestamp dateStr) {
		try {
			return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dateStr);
		} catch (Exception e) {
			logger.error(e.getMessage());
			try {
				return new SimpleDateFormat("yyyy-MM-dd").format(dateStr);
			} catch (Exception ex) {
				ex.printStackTrace();
				logger.error(ex.getMessage());
				return null;
			}
		}
	}

	/**
	 * 将数据库java.sql.Date转为yyyy-MM-dd字符串
	 *
	 * @param dateStr p
	 * @return r
	 */
	public static String toDateStr(java.sql.Date dateStr) {
		try {
			return new SimpleDateFormat("yyyy-MM-dd").format(dateStr);
		} catch (Exception e) {
			logger.error(e.getMessage());
			try {
				return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(dateStr);//TODO:错误处理方法.
			} catch (Exception ex) {
				logger.error(ex.getMessage());
				ex.printStackTrace();
				return null;
			}
		}
	}

	/**
	 * 格式化
	 */
	private static String format(TemporalAccessor temporal, String pattern) {
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
		return formatter.format(temporal);
	}

	/**
	 * String数组转为字符串:用,拼接
	 *
	 * @param obj
	 * @return
	 */
	public static String toString(String[] obj) {
		StringBuilder rs = new StringBuilder();
		try {
			if (obj != null && obj.length > 0) {
				for (int i = 0; i < obj.length; i++) {
					if (i == 0) {
						rs.append(obj[i]);
					} else {
						rs.append(",").append(obj[i]);
					}
				}
			}
			return rs.toString();
		} catch (Exception e) {
			logger.error(e.getMessage());
			return rs.toString();
		}
	}
}
